<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Use correct character set. -->
    <meta charset="utf-8" />
    <!-- Tell IE to use the latest, best version. -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <title>Hello World!</title>
    <!-- <script src="../Build/Cesium/Cesium.js"></script> -->
    <script src="../Build/CesiumUnminified/Cesium.js"></script>
    <script src="jquery-2.0.3.js"></script>
    <style>
      @import url(../Build/Cesium/Widgets/widgets.css);

      html,
      body,
      #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>

  <body>
    <div
      id="content"
      style="
        position: absolute;
        right: 0px;
        right: 0px;
        width: 300px;
        height: 200px;
      "
    ></div>
    <div id="cesiumContainer"></div>
    <script>
      function WebGLGlobeDataSource(name) {
        //All public configuration is defined as ES5 properties
        //These are just the "private" variables and their defaults.
        this._name = name;
        this._changed = new Cesium.Event();
        this._error = new Cesium.Event();
        this._isLoading = false;
        this._loading = new Cesium.Event();
        this._entityCollection = new Cesium.EntityCollection();
        this._seriesNames = [];
        this._seriesToDisplay = undefined;
        this._heightScale = 10000000;
        this._entityCluster = new Cesium.EntityCluster();
      }

      Object.defineProperties(Cesium, DemoTileProvider.prototype, {
        //The below properties must be implemented by all DataSource instances

        /**
         * Gets a human-readable name for this instance.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {String}
         */
        name: {
          get: function () {
            return this._name;
          },
        },
        /**
         * Since WebGL Globe JSON is not time-dynamic, this property is always undefined.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {DataSourceClock}
         */
        clock: {
          value: undefined,
          writable: false,
        },
        /**
         * Gets the collection of Entity instances.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {EntityCollection}
         */
        entities: {
          get: function () {
            return this._entityCollection;
          },
        },
        /**
         * Gets a value indicating if the data source is currently loading data.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Boolean}
         */
        isLoading: {
          get: function () {
            return this._isLoading;
          },
        },
        /**
         * Gets an event that will be raised when the underlying data changes.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Event}
         */
        changedEvent: {
          get: function () {
            return this._changed;
          },
        },
        /**
         * Gets an event that will be raised if an error is encountered during
         * processing.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Event}
         */
        errorEvent: {
          get: function () {
            return this._error;
          },
        },
        /**
         * Gets an event that will be raised when the data source either starts or
         * stops loading.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Event}
         */
        loadingEvent: {
          get: function () {
            return this._loading;
          },
        },

        //These properties are specific to this DataSource.

        /**
         * Gets the array of series names.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {String[]}
         */
        seriesNames: {
          get: function () {
            return this._seriesNames;
          },
        },
        /**
         * Gets or sets the name of the series to display.  WebGL JSON is designed
         * so that only one series is viewed at a time.  Valid values are defined
         * in the seriesNames property.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {String}
         */
        seriesToDisplay: {
          get: function () {
            return this._seriesToDisplay;
          },
          set: function (value) {
            this._seriesToDisplay = value;

            //Iterate over all entities and set their show property
            //to true only if they are part of the current series.
            var collection = this._entityCollection;
            var entities = collection.values;
            collection.suspendEvents();
            for (var i = 0; i < entities.length; i++) {
              var entity = entities[i];
              entity.show = value === entity.seriesName;
            }
            collection.resumeEvents();
          },
        },
        /**
         * Gets or sets the scale factor applied to the height of each line.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Number}
         */
        heightScale: {
          get: function () {
            return this._heightScale;
          },
          set: function (value) {
            if (value <= 0) {
              throw new Cesium.DeveloperError("value must be greater than 0");
            }
            this._heightScale = value;
          },
        },
        /**
         * Gets whether or not this data source should be displayed.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {Boolean}
         */
        show: {
          get: function () {
            return this._entityCollection;
          },
          set: function (value) {
            this._entityCollection = value;
          },
        },
        /**
         * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
         * @memberof WebGLGlobeDataSource.prototype
         * @type {EntityCluster}
         */
        clustering: {
          get: function () {
            return this._entityCluster;
          },
          set: function (value) {
            if (!Cesium.defined(value)) {
              throw new Cesium.DeveloperError("value must be defined.");
            }
            this._entityCluster = value;
          },
        },
      });

      /**
       * Asynchronously loads the GeoJSON at the provided url, replacing any existing data.
       * @param {Object} url The url to be processed.
       * @returns {Promise} a promise that will resolve when the GeoJSON is loaded.
       */
      WebGLGlobeDataSource.prototype.loadUrl = function (url) {
        if (!Cesium.defined(url)) {
          throw new Cesium.DeveloperError("url is required.");
        }

        //Create a name based on the url
        var name = Cesium.getFilenameFromUri(url);

        //Set the name if it is different than the current name.
        if (this._name !== name) {
          this._name = name;
          this._changed.raiseEvent(this);
        }

        //Use 'when' to load the URL into a json object
        //and then process is with the `load` function.
        var that = this;
        return Cesium.Resource.fetchJson(url)
          .then(function (json) {
            return that.load(json, url);
          })
          .otherwise(function (error) {
            //Otherwise will catch any errors or exceptions that occur
            //during the promise processing. When this happens,
            //we raise the error event and reject the promise.
            this._setLoading(false);
            that._error.raiseEvent(that, error);
            return Cesium.when.reject(error);
          });
      };

      /**
       * Loads the provided data, replacing any existing data.
       * @param {Array} data The object to be processed.
       */
      WebGLGlobeDataSource.prototype.load = function (data) {
        //>>includeStart('debug', pragmas.debug);
        if (!Cesium.defined(data)) {
          throw new Cesium.DeveloperError("data is required.");
        }
        //>>includeEnd('debug');

        //Clear out any data that might already exist.
        this._setLoading(true);
        this._seriesNames.length = 0;
        this._seriesToDisplay = undefined;

        var heightScale = this.heightScale;
        var entities = this._entityCollection;

        //It's a good idea to suspend events when making changes to a
        //large amount of entities.  This will cause events to be batched up
        //into the minimal amount of function calls and all take place at the
        //end of processing (when resumeEvents is called).
        entities.suspendEvents();
        entities.removeAll();

        //WebGL Globe JSON is an array of series, where each series itself is an
        //array of two items, the first containing the series name and the second
        //being an array of repeating latitude, longitude, height values.
        //
        //Here's a more visual example.
        //[["series1",[latitude, longitude, height, ... ]
        // ["series2",[latitude, longitude, height, ... ]]

        // Loop over each series
        for (var x = 0; x < data.length; x += 5) {
          var series = data[x];
          var seriesName = series[0];
          var coordinates = series[1];

          //Add the name of the series to our list of possible values.
          this._seriesNames.push(seriesName);

          //Make the first series the visible one by default
          var show = x === 0;
          if (show) {
            this._seriesToDisplay = seriesName;
          }

          //Now loop over each coordinate in the series and create
          // our entities from the data.
          for (var i = 0; i < coordinates.length; i += 3) {
            var latitude = coordinates[i];
            var longitude = coordinates[i + 1];
            var height = coordinates[i + 2];

            //Ignore lines of zero height.
            if (height === 0) {
              continue;
            }

            var color = Cesium.Color.fromHsl(0.6 - height * 0.5, 1.0, 0.5);
            var surfacePosition = Cesium.Cartesian3.fromDegrees(
              longitude,
              latitude,
              0
            );
            var heightPosition = Cesium.Cartesian3.fromDegrees(
              longitude,
              latitude,
              height * heightScale
            );

            //WebGL Globe only contains lines, so that's the only graphics we create.
            var polyline = new Cesium.PolylineGraphics();
            polyline.material = new Cesium.ColorMaterialProperty(color);
            polyline.width = new Cesium.ConstantProperty(2);
            polyline.arcType = new Cesium.ConstantProperty(Cesium.ArcType.NONE);
            polyline.positions = new Cesium.ConstantProperty([
              surfacePosition,
              heightPosition,
            ]);

            // The polyline instance itself needs to be on an entity.
            var entity = new Cesium.Entity({
              id: seriesName + " index " + i.toString(),
              show: show,
              polyline: polyline,
              seriesName: seriesName, //Custom property to indicate series name
            });

            // var entity = viewer.entities.add({//Cylinder圆柱体
            //     name: 'Green cylinder with black outline',
            //     position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 200000.0),
            //     cylinder: {
            //         length: 400000.0,
            //         topRadius: 200000.0,//圆柱体的顶部半径。
            //         bottomRadius: 200000.0,//    圆柱体底部的半径。
            //         material: Cesium.Color.GREEN.withAlpha(0.5),//绿色半透明
            //         outline: true,//轮廓
            //         outlineColor: Cesium.Color.DARK_GREEN//轮廓颜色深绿色
            //     }
            // });
            // //Add the entity to the collection.
            // entities.add(entity);

            var greenCylinder = viewer.entities.add({
              //Cylinder圆柱体
              name: "Green cylinder with black outline",
              position: surfacePosition,
              cylinder: {
                length: height * 1000000,
                topRadius: 10000.0, //圆柱体的顶部半径。
                bottomRadius: 10000.0, //    圆柱体底部的半径。
                material: new Cesium.ColorMaterialProperty(color), //绿色半透明
                fill: true,
                // outline: true,//轮廓
                // outlineColor: Cesium.Color.DARK_GREEN//轮廓颜色深绿色
              },
            });
          }
        }

        //Once all data is processed, call resumeEvents and raise the changed event.
        entities.resumeEvents();
        this._changed.raiseEvent(this);
        this._setLoading(false);
      };

      WebGLGlobeDataSource.prototype._setLoading = function (isLoading) {
        if (this._isLoading !== isLoading) {
          this._isLoading = isLoading;
          this._loading.raiseEvent(this, isLoading);
        }
      };

      //Now that we've defined our own DataSource, we can use it to load
      //any JSON data formatted for WebGL Globe.
      var dataSource = new WebGLGlobeDataSource();
      dataSource
        .loadUrl("./SampleData/population909500.json")
        .then(function () {
          //After the initial load, create buttons to let the user switch among series.
          function createSeriesSetter(seriesName) {
            return function () {
              dataSource.seriesToDisplay = seriesName;
            };
          }
        });

      //Create a Viewer instances and add the DataSource.
      var viewer = new Cesium.Viewer("cesiumContainer", {
        //需要进行可视化的数据源的集合
        animation: false, //是否显示动画控件
        shouldAnimate: true,
        homeButton: false, //是否显示Home按钮
        fullscreenButton: false, //是否显示全屏按钮
        baseLayerPicker: false, //是否显示图层选择控件
        geocoder: false, //是否显示地名查找控件
        timeline: false, //是否显示时间线控件
        sceneModePicker: true, //是否显示投影方式控件
        navigationHelpButton: false, //是否显示帮助信息控件
        infoBox: false, //是否显示点击要素之后显示的信息
        requestRenderMode: true, //启用请求渲染模式
        scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
        sceneMode: 3, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
        fullscreenElement: document.body, //全屏时渲染的HTML元素 暂时没发现用处
        //天地图是官方开元的地图，不需要密钥
        imageryProvider: new Cesium.UrlTemplateImageryProvider({
          url:
            "http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}&s=Gali",
        }),
      });
      //viewer.dataSources.add(dataSource);

      // var greenCylinder = viewer.entities.add({//Cylinder圆柱体
      //     name: 'Green cylinder with black outline',
      //     position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 200000.0),
      //     cylinder: {
      //         length: 400000.0,
      //         topRadius: 200000.0,//圆柱体的顶部半径。
      //         bottomRadius: 200000.0,//    圆柱体底部的半径。
      //         material: Cesium.Color.GREEN.withAlpha(0.5),//绿色半透明
      //         outline: true,//轮廓
      //         outlineColor: Cesium.Color.DARK_GREEN//轮廓颜色深绿色
      //     }
      // });

      viewer.zoomTo(viewer.entities);
    </script>
  </body>
</html>
